#include<fstream>
#include <iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/objdetect/objdetect.hpp>
#include<opencv2/ml/ml.hpp>


using namespace cv;
using namespace std;

#define PosSamNo 2400          //positive samples
#define NegSamNo 12000         //negtive samples

class MySVM : public CvSVM
{
public:
    //获得SVM的决策函数中的alpha数组
    double * get_alpha_vector()
    {
        return this->decision_func->alpha;
    }
    
    //获得SVM的决策函数中的rho参数,即偏移量
    float get_rho()
    {
        return this->decision_func->rho;
    }
};



int main()
{
    //detector window(64,128) block(16,16) stride(8,8) cell(8,8)bin:9
    HOGDescriptor hog(Size(64,128),Size(16,16),Size(8,8),Size(8,8),9);
    int DescriptorDim;//dimension of HOG
    MySVM svm;//classifier of SVM
    svm.load("/Users/new/Desktop/HOG/INRIADATA/normalized_images/train/train_thr/SVM_mix/SVM_HOG.xml");
   
    //-------------------------------------------------------------------------------------------
    //              replace fix classifier in opencv with our trained Svm
    //-------------------------------------------------------------------------------------------
    DescriptorDim=svm.get_var_count();
    int supportVectorNum=svm.get_support_vector_count();
    cout<<"No of support vectors: "<<supportVectorNum<<endl;
    Mat alphaMat=Mat::zeros(1,supportVectorNum,CV_32FC1);
    Mat supportVectorMat=Mat::zeros(supportVectorNum,DescriptorDim,CV_32FC1);
    Mat resultMat=Mat::zeros(1,DescriptorDim,CV_32FC1);
    
    //copy data of support vector to supportVectorMat
    for(int i=0;i!=supportVectorNum;++i)
    {
        const float* pSVData=svm.get_support_vector(i);//return i th data p of sopport vector
        for(int j=0;j!=DescriptorDim;++j)
        {
            supportVectorMat.at<float>(i,j)=pSVData[j];
        }
    }
    //copy data of alpha to alphaMat
    double* pALPHADATA=svm.get_alpha_vector();
    for(int i=0;i!=supportVectorNum;++i)
    {
        alphaMat.at<float>(0,i)=pALPHADATA[i];
    }
    //compute -(alphaMat * supportVectorMat) in resultMat
    resultMat=-1.15*alphaMat*supportVectorMat;
    vector<float>myDetector;
    for(int i=0;i!=DescriptorDim;++i)
    {
        myDetector.push_back(resultMat.at<float>(0,i));
    }
    //add rho
    myDetector.push_back(svm.get_rho());
    cout<<"dimension of detector: "<<myDetector.size()<<endl;
    //set HOG descriptor
    HOGDescriptor myHOG;
    myHOG.setSVMDetector(myDetector);
    //----------------------------------------------------------------------------------------------
    //                 read image to detect HOG pedestrain
    //----------------------------------------------------------------------------------------------
    int testNum=179;
    string ImgName;
    ifstream inFile("/Users/new/Desktop/HOG/INRIADATA/normalized_images/TestData/test_pos.txt");
    for(int num=0;num!=testNum && getline(inFile,ImgName);++num)
    {
        ImgName="/Users/new/Desktop/HOG/INRIADATA/normalized_images/TestData/"+ImgName;
    Mat src=imread(ImgName);
    vector<Rect>found,found_filtered;//rect array
    cout<<"doing multiscale HOG pedestrain detection"<<endl;
    myHOG.detectMultiScale(src,found,0,Size(8,8),Size(48,48),1.15,5);//doing multiscale HOG
    cout<<"find No of rect array: "<<found.size()<<endl;
    //----------------------------------------------------------------------------------------------
    //                 non-maxximal suppression
    //----------------------------------------------------------------------------------------------
    for(int i=0;i!=found.size();++i)
    {
        Rect r=found[i];
        int j=0;
        for(;j!=found.size();++j)
            if(j!=i && (r & found[j])==r)
                break;
        if(j==found.size())
            found_filtered.push_back(r);
    }
    //draw rect window
    for(int i=0;i!=found_filtered.size();++i)
    {
        Rect r=found_filtered[i];
        r.x += cvRound(r.width*0.1);
        r.width=cvRound(r.width*0.8);
        r.y += cvRound(r.height*0.07);
        r.height =cvRound(r.height*0.8);
        rectangle(src,r.tl(),r.br(),Scalar(0,255,0),3);
    }
    namedWindow("src",CV_WINDOW_AUTOSIZE);
    imshow("src",src);
        if(waitKey(30)>=0)
        break;
    }
    system("pause");
    return 0;
}
